package ae.pcfc.cldos.online.common.facade.provider;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.transaction.annotation.Transactional;

import ae.pcfc.cldos.online.common.ConstantsCommon;
import ae.pcfc.cldos.online.common.ConstantsCommon.Steps;
import ae.pcfc.cldos.online.common.UltimusConstants.AdminDecision;
import ae.pcfc.cldos.online.common.clddb.domain.AppMetaData;
import ae.pcfc.cldos.online.common.clddb.domain.ApplicationStatus;
import ae.pcfc.cldos.online.common.clddb.domain.Process;
import ae.pcfc.cldos.online.common.clddb.domain.ReviewComments;
import ae.pcfc.cldos.online.common.clddb.domain.TaskMaster;
import ae.pcfc.cldos.online.common.clddb.domain.manager.AppMetaDataDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.ReviewCommentsDOM;
import ae.pcfc.cldos.online.common.clddb.domain.manager.provider.AppMetaDataDOMImpl;
import ae.pcfc.cldos.online.common.etksdb.domain.Client;
import ae.pcfc.cldos.online.common.etksdb.domain.User;
import ae.pcfc.cldos.online.common.etksdb.domain.manager.ClientDOM;
import ae.pcfc.cldos.online.common.etksdb.domain.manager.UserDomainObjectManager;
import ae.pcfc.cldos.online.common.exception.BadAppException;
import ae.pcfc.cldos.online.common.facade.BaseFacade;
import ae.pcfc.cldos.online.common.facade.GeneralAdminFacade;
import ae.pcfc.cldos.online.common.manager.FNPManager;
import ae.pcfc.cldos.online.common.manager.FileStorageManager;
import ae.pcfc.cldos.online.common.manager.GSEmployeeDetailsManager;
import ae.pcfc.cldos.online.common.manager.GsInfoManager;
import ae.pcfc.cldos.online.common.manager.TaskAndNotificationsManager;
import ae.pcfc.cldos.online.common.tscdb.domain.manager.TTscClientCompanyDOM;
import ae.pcfc.cldos.online.common.vo.BackOfficeAdminVO;
import ae.pcfc.cldos.online.fnp.service.client.vo.FNPFinalPaymentResponseVO;
import ae.pcfc.cldos.online.gs.service.client.vo.NotificationVO;
import ae.pcfc.cldos.online.gs.service.client.vo.StepCommentsVO;
import ae.pcfc.cldos.online.net.service.vo.AttachmentVO;
import ae.pcfc.cldos.online.wf.service.client.GenericVisaWF;
import ae.pcfc.cldos.online.wf.service.client.vo.base.CompleteStepVO;
import ae.pcfc.cldos.online.wf.service.client.vo.gvar.DataValidationActionGVarVO;
import ae.pcfc.cldos.online.net.ConstantsNET;

/**
 * 
 * @author arosa
 *
 */
public class GeneralAdminFacadeImpl extends BaseFacade implements GeneralAdminFacade {

	private AppMetaDataDOM appMetaDataDOM;
	
	private ReviewCommentsDOM reviewCommentsDOM;
	
	private GsInfoManager gsInfoManager;
	
	private FileStorageManager fileStorageManager;
	
	private GSEmployeeDetailsManager gsEmployeeDetailsManager;
	
	
	public GSEmployeeDetailsManager getGsEmployeeDetailsManager() {
		return gsEmployeeDetailsManager;
	}

	public void setGsEmployeeDetailsManager(
			GSEmployeeDetailsManager gsEmployeeDetailsManager) {
		this.gsEmployeeDetailsManager = gsEmployeeDetailsManager;
	}

	public void setFileStorageManager(FileStorageManager fileStorageManager) {
		this.fileStorageManager = fileStorageManager;
	}
	
	public void setGsInfoManager(GsInfoManager gsInfoManager) {
		this.gsInfoManager = gsInfoManager;
	}

	public void setReviewCommentsDOM(ReviewCommentsDOM reviewCommentsDOM) {
		this.reviewCommentsDOM = reviewCommentsDOM;
	}

	public void setAppMetaDataDOM(AppMetaDataDOM appMetaDataDOM) {
		this.appMetaDataDOM = appMetaDataDOM;
	}
	
	private GenericVisaWF genericVisaWF;
	
	public void setGenericVisaWF(GenericVisaWF genericVisaWF) {
		this.genericVisaWF = genericVisaWF;
	}
	
	private ClientDOM clientDOM;
	
	public void setClientDOM(ClientDOM clientDOM) {
		this.clientDOM = clientDOM;
	}
	
	private TTscClientCompanyDOM tTscClientCompanyDOM;
	
	public void settTscClientCompanyDOM(
			TTscClientCompanyDOM tTscClientCompanyDOM) {
		this.tTscClientCompanyDOM = tTscClientCompanyDOM;
	}
	
	private FNPManager fnpManager;
	
	public void setFnpManager(FNPManager fnpManager) {
		this.fnpManager = fnpManager;
	}
	
	private UserDomainObjectManager userDomainObjectManager;
	
	public void setUserDomainObjectManager(
			UserDomainObjectManager userDomainObjectManager) {
		this.userDomainObjectManager = userDomainObjectManager;
	}
	
	private TaskAndNotificationsManager taskAndNotificationsManager;
	
	public void setTaskAndNotificationsManager(
			TaskAndNotificationsManager taskAndNotificationsManager) {
		this.taskAndNotificationsManager = taskAndNotificationsManager;
	}
	
	@Transactional(rollbackFor=Exception.class)
	public String getInitiatedByFromAppMetaDataById(String applicationId) throws BadAppException , Exception {
		return appMetaDataDOM.getPlainAppMetaDataById(applicationId).getWfInitiatedBy();
	}
	
	@Transactional(rollbackFor=Exception.class)
	public String reviewByBackOffice(BackOfficeAdminVO backOfficeAdminVO) throws Exception{
		
		//Move Data to .net part 
		AppMetaData appMetaData = appMetaDataDOM.getAppMetaDataById(backOfficeAdminVO.getStrApplicationId());
		
		if(!appMetaData.getStatusCode().equals(ApplicationStatus.STATUS_APPROVED_BY_ONLINE_ADMIN)){
			throw new BadAppException("Allready submited");
		}
		if(!AppMetaDataDOMImpl.STEPS_STATUSES_MAPPING.get(Steps.DOCUMENT_AND_DATA_VALIDATION).contains(appMetaData.getStatusCode())){
			throw new BadAppException("Bad app");
		}
		
		Long clientId = appMetaData.getClientId();
		Client client = clientDOM.getClientById(clientId);
		String companyLicenseNumber = 
		tTscClientCompanyDOM.getLicenseNumberNyTrakheesId(client.getCTrakheesId());
		
		taskAndNotificationsManager.completeAllByAppId(appMetaData.getApplicationId());

		User user = userDomainObjectManager.findUserById(appMetaData.getUserId());
		
		List<AttachmentVO> attachments = new ArrayList<AttachmentVO>(2);
		
		if(backOfficeAdminVO.getStrActionType().equals(AdminDecision.APPROVED.getAdminDecision())){
			if(appMetaData.getProcessCode().equals(Process.PROCESS_CANCEL_VISIT_VISA)){
				gsEmployeeDetailsManager.approveVisitVisaCancel(appMetaData.getClientRefNo(),appMetaData.getApplicationId().toString(),companyLicenseNumber);
				appMetaData.setStatusCode(ApplicationStatus.STATUS_COMPLETED);
			}else{
				appMetaData.setStatusCode(ApplicationStatus.STATUS_APPROVED_BY_GENERAL_ADMIN);
			}
			if(appMetaData.getPaymentAdviceNo()!=null){
				FNPFinalPaymentResponseVO fnpFinalPaymentResponseVO = 
						fnpManager.finalizePayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
						appMetaData.getPaymentAdviceNo());
				attachments.add(fnpFinalPaymentResponseVO.getAttachmentVO());
			}
			if(appMetaData.getBgPaymentAdviceNo()!=null){
				FNPFinalPaymentResponseVO fnpFinalPaymentResponseVOBG = fnpManager.finalizePayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
							appMetaData.getBgPaymentAdviceNo());
				attachments.add(fnpFinalPaymentResponseVOBG.getAttachmentVO());
			}
			gsInfoManager.updateAppReqWorkFlowStatus(appMetaData.getClientRefNo(), ConstantsNET.STATUS_IN_PROGRESS);
		} else if(backOfficeAdminVO.getStrActionType().equals(AdminDecision.REJECTED.getAdminDecision()))  {
			
			appMetaData.setStatusCode(ApplicationStatus.STATUS_REJECTED_BY_GENERAL_ADMIN);
			
			taskAndNotificationsManager.sendTask(appMetaData, TaskMaster.__ALL_RESUBMIT);
			if(appMetaData.getPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
					appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
			}
			if(appMetaData.getBgPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
						appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
				if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
					gsInfoManager.removeEmpVisaBG(companyLicenseNumber, user.getUUsername());
				} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)){
					gsInfoManager.removeVisitVisaBG(companyLicenseNumber, user.getUUsername());
				}
			}
			
			gsInfoManager.rejectAppRequest(appMetaData.getClientRefNo());
			
		} else {
			
			appMetaData.setStatusCode(ApplicationStatus.STATUS_CANCELED_BY_GENERAL_ADMIN);
			if(appMetaData.getPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
					appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
			}
			if(appMetaData.getBgPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
						appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
				if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
					gsInfoManager.removeEmpVisaBG(companyLicenseNumber, user.getUUsername());
				} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)) {
					gsInfoManager.removeVisitVisaBG(companyLicenseNumber, user.getUUsername());
				}
			}
			
			gsInfoManager.cancelGSAppRequest(appMetaData.getClientRefNo());
			
		}
		if(!backOfficeAdminVO.getStrActionType().equals(AdminDecision.APPROVED.getAdminDecision())){
			fileStorageManager.deletePaymentVouchers(appMetaData.getApplicationId());
		}
		
		// Send comments to GS
		StepCommentsVO stepCommentsVO = new StepCommentsVO();
		stepCommentsVO.setApplicationId(appMetaData.getClientRefNo());
		stepCommentsVO.setCommentBy(backOfficeAdminVO.getStrUserName());
		stepCommentsVO.setCommentDate(new Date());
		stepCommentsVO.setCommentDesc(backOfficeAdminVO.getStrComments());
		stepCommentsVO.setProcessCode(appMetaData.getProcessCode());
		stepCommentsVO.setActionDesc(backOfficeAdminVO.getStrActionType());
		gsInfoManager.insertStepComments(stepCommentsVO);
		
		/*Send notification*/
		NotificationVO notificationVO = new NotificationVO();
		notificationVO.setCoLicNo(companyLicenseNumber);
		notificationVO.setAttachments(attachments);
		notificationVO.setOnlineAppId(appMetaData.getApplicationId().toString());
		Map<Object, Object> parameters = new HashMap<Object, Object>();
		parameters.put("comments", backOfficeAdminVO.getStrComments());
		notificationVO.setParameters(parameters);
		taskAndNotificationsManager.sendNotification(appMetaData, notificationVO);
		
		appMetaDataDOM.update(appMetaData);
		
		/*add action comment*/
		
		ReviewComments reviewComments = new ReviewComments();
		reviewComments.setApplicationId(appMetaData.getApplicationId());
		reviewComments.setStatusCode(appMetaData.getStatusCode());
		reviewComments.setRcUserName(ConstantsCommon.BACK_OFFICE_USER);
		reviewComments.setRcComments(backOfficeAdminVO.getStrComments());
		reviewCommentsDOM.add(reviewComments);
		
		//Call Ultimus 
		
		DataValidationActionGVarVO dataValidationActionGVarVO = new DataValidationActionGVarVO();
		if(backOfficeAdminVO.getStrActionType().equals(AdminDecision.APPROVED.getAdminDecision())){
			dataValidationActionGVarVO.setG_ApplicationID(appMetaData.getClientRefNo());
		} else {
			dataValidationActionGVarVO.setG_ApplicationID(appMetaData.getApplicationId().toString());
		}
		dataValidationActionGVarVO.setG_DataValidationDecision(backOfficeAdminVO.getStrActionType());
		
		CompleteStepVO completeStepVO = new CompleteStepVO();
		completeStepVO.setStrStepName(backOfficeAdminVO.getStrStepName());
		completeStepVO.setStrUserName(backOfficeAdminVO.getStrUserName());
		completeStepVO.setnIncidentNumber(new Integer(backOfficeAdminVO.getStrIncidentNo()));
		
		try{
			genericVisaWF.completeStep(appMetaData.getProcessCode(), completeStepVO, dataValidationActionGVarVO);
		} catch(Exception  e){
			e.printStackTrace();
			if(appMetaData.getPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(),
					appMetaData.getPaymentAdviceNo(),appMetaData.getClientRefNo());
			}
			if(appMetaData.getBgPaymentAdviceNo()!=null){
				fnpManager.cancelPayment(appMetaData.getApplicationId().toString(), user.getUUsername(), 
						appMetaData.getBgPaymentAdviceNo(),appMetaData.getClientRefNo());
				if(appMetaData.getProcessCode().equals(Process.PROCESS_EMPLOYMENT_VISA)){
					gsInfoManager.removeEmpVisaBG(companyLicenseNumber, user.getUUsername());
				} else if(appMetaData.getProcessCode().equals(Process.PROCESS_VISIT_VISA)) {
					gsInfoManager.removeVisitVisaBG(companyLicenseNumber, user.getUUsername());
				}
			}
			//::TODO rollback .NET;
			throw new Exception(e);
		}
		return appMetaData.getClientRefNo();
	}

}
